/**
 * Copyright @ 2019 HoldTime Inner Mongolia Co. Ltd.
 */
package com.holdtime.jtt809dataservice.server.processor;

import com.edata.common.BytesUtil;
import com.holdtime.common.utils.general.ApiResponseModel;
import com.holdtime.common.utils.general.BaseResultCode;
import com.holdtime.jtt809dataservice.business.api.LinkService;
import com.holdtime.jtt809dataservice.common.bean.MainLinkLoginReqDTO;
import com.holdtime.jtt809dataservice.common.bean.MainLinkLoginResDTO;
import com.holdtime.jtt809dataservice.common.event.MessageReceiveEvent;
import com.holdtime.jtt809dataservice.common.process.ProtocolProcessor;
import com.holdtime.jtt809dataservice.server.handler.SubLinksHandler;
import com.holdtime.jtt809dataservice.server.socket.TcpClient;
import com.holdtime.jtt809dataservice.server.util.LinksManager;
import io.netty.channel.ChannelHandlerContext;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import protocol.jtt809.JTT809Packet;
import protocol.jtt809.ProtocolJT809;
import protocol.jtt809.body.*;

import java.net.InetSocketAddress;

/**
 * 项目名称： jtt809gateway<br>
 * 功能描述： UpConnectReqProcessor概述：主链路登陆请求消息处理<br>
 * 创  建 人： guoai<br>
 * 创建日期： 2019年7月26日<br>
 * 修  改 人：  <br>
 * 修改时间：<br>
 * 修改内容：<br>
 * 版      本： 1.0.0
 */
@Component
public @Slf4j class UpConnectReqProcessor implements ProtocolProcessor {

    @Resource
    private ProtocolJT809 protocolJT809;
    @Resource
    private SubLinksHandler handler;
    @Resource
    private LinkService linkService;

    @Override
    public int getMsgID() {
        return UpConnectReq.MSG_ID;
    }

    @Override
    public void process(MessageReceiveEvent event) {
        JTT809Packet<RawBody> source = event.getSource();
        RawBody body = source.getBody();
        UpConnectReq req = new UpConnectReq();
        req.from(body.getRaw());
        ChannelHandlerContext session = event.getChannelHandlerContext();

        try {
            InetSocketAddress inetSocketAddress = (InetSocketAddress) session.channel().remoteAddress();
            String ip = inetSocketAddress.getAddress().getHostAddress();
            MainLinkLoginReqDTO mainLinkLoginReqDTO = new MainLinkLoginReqDTO();
            mainLinkLoginReqDTO.setIp(ip);
            mainLinkLoginReqDTO.setUserid(req.getUserid());
            mainLinkLoginReqDTO.setPassword(req.getPassword());
            mainLinkLoginReqDTO.setJrm(source.getMsgGnsscenterid());
            ApiResponseModel<MainLinkLoginResDTO> model = linkService.dealMainLinkLoginReq(mainLinkLoginReqDTO);
            if (model.getResultCode() == BaseResultCode.SUCCESS.getCode()) {
                MainLinkLoginResDTO record = model.getRecord();
                UpConnectRsp rsp = new UpConnectRsp();
                rsp.setResult((byte) record.getResult());
                int r = (int) (Math.random() * (Integer.MAX_VALUE - 1) + 1);
                rsp.setVerifyCode(r);
                JTT809Packet<UpConnectRsp> packet = protocolJT809.getPacket(rsp, UpConnectRsp.MSG_ID,
                        source.getMsgGnsscenterid());
                session.write(packet);
                System.out.println("主链路登陆成功应答" + BytesUtil.changebytetohexstring(packet.array()));
                LinksManager.putMainLink(source.getMsgGnsscenterid(), session);

                // 建立从链路连接
                if (rsp.getResult() != 0) return;
                TcpClient tcpClient = new TcpClient(handler, req.getDownLinkIp(), req.getDownLinkPort(), () -> {
                    LinksManager.removeSubLink(source.getMsgGnsscenterid());
                    DownDisconnectInform inform = new DownDisconnectInform();
                    inform.setErrorCode((byte) 0x01);
                    JTT809Packet<DownDisconnectInform> disconnPacket = protocolJT809.getPacket(inform,
                            DownDisconnectInform.MSG_ID, source.getMsgGnsscenterid());
                    session.write(disconnPacket);
                });
                boolean isConnected = tcpClient.connect();
                if (!isConnected) {//连接失败释放连接，主链路发送从链路断开通知消息
                    log.error(source.getMsgGnsscenterid() + "从链接连接失败" + req.getDownLinkIp() + ":" + req.getDownLinkPort());
                    tcpClient.dispose();
                    DownDisconnectInform inform = new DownDisconnectInform();
                    inform.setErrorCode((byte) 0x00);
                    JTT809Packet<DownDisconnectInform> disconnPacket = protocolJT809.getPacket(inform,
                            DownDisconnectInform.MSG_ID, source.getMsgGnsscenterid());
                    session.write(disconnPacket);
                } else {//连接成功，发送从链路连接请求消息
                    DownConnectReq downConnectReq = new DownConnectReq();
                    downConnectReq.setVerifyCode(rsp.getVerifyCode());
                    JTT809Packet<DownConnectReq> dcrp = protocolJT809.getPacket(downConnectReq,
                            DownConnectReq.MSG_ID, source.getMsgGnsscenterid());
                    byte[] bytes = dcrp.array();
                    log.error("发送消息给车辆-bytes：{}", BytesUtil.changebytetohexstring(bytes));
                    tcpClient.send(bytes);
                    LinksManager.putSubLink(source.getMsgGnsscenterid(), tcpClient);
                    log.error(source.getMsgGnsscenterid() + "从链接连接成功" + req.getDownLinkIp() + ":" + req.getDownLinkPort());
                }
            } else {
                log.error("主链路登陆失败:{}", model.getMsg());
            }

        } catch (Exception e) {
            log.error("主链路登陆处理异常：", e);
        }
    }

}
